package com.example.whatrubbish.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.whatrubbish.model.SearchRecord;
import com.example.whatrubbish.service.RubbishService;
import com.example.whatrubbish.service.SearchRecordService;
import com.example.whatrubbish.utils.*;
import com.example.whatrubbish.vo.RubbishWithSort;
import org.apdplat.word.WordSegmenter;
import org.apdplat.word.segmentation.Word;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.net.URL;
import java.util.*;

/**
 * 通用物体和场景识别
 * 语音识别
 */
@CrossOrigin
@RestController
@RequestMapping("/search")
public class AdvancedGeneral {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RubbishService rubbishService;
    @Autowired
    SearchRecordService searchRecordService;

    private final boolean METHOD_RAW = false; // 默认以json方式上传音频文件
    //  填写网页上申请的appkey 如 $apiKey="g8eBUMSokVB1BHGmgxxxxxx"
    private final String APP_KEY = "C1vV9CCW9fM9pSsQwcbTFU5o";
    // 填写网页上申请的APP SECRET 如 $SECRET_KEY="94dc99566550d87f8fa8ece112xxxxx"
    private final String SECRET_KEY = "czCDlw5gxdvciZ2Sd7yQDEOeyb9mqi0M";
    // 需要识别的文件
    private final String FILENAME = "16k.pcm";
    // 文件格式, 支持pcm/wav/amr 格式，极速版额外支持m4a 格式
    // private final String FORMAT = FILENAME.substring(FILENAME.length() - 3);
    private String CUID = "1234567JAVA";

    // 采样率固定值
    private final int RATE = 16000;

    private String URL;

    private int DEV_PID;

    //private int LM_ID;//测试自训练平台需要打开此注释

    private String SCOPE;

    //  普通版 参数
    {
        URL = "https://vop.baidu.com/server_api"; // 可以改为https
        //  1537 表示识别普通话，使用输入法模型。 其它语种参见文档
        DEV_PID = 1537;
        SCOPE = "audio_voice_assistant_get";
    }

    /**
     * 图像识别
     *
     * 重要提示代码中所需工具类
     * FileUtil,Base64Util,HttpUtil,GsonUtils请从
     * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
     * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
     * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
     * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
     * 下载
     */
    @RequestMapping(value = "/image", method = RequestMethod.POST)
    public Object imageAdvancedGeneral(@RequestParam("file") MultipartFile file) {
        JsonResult jsonResult;
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/image-classify/v2/advanced_general";
        try {
            // 本地文件路径
//            String filePath = "C:\\Users\\Administrator\\Documents\\Tencent Files\\326063404\\FileRecv\\MobileFile\\F5CA5F9647824E6586DADED85945C6F9.png";
            byte[] imgData = file.getBytes();
//            byte[] imgData = FileUtil.readFileByBytes(filePath);
            String imgStr = Base64Util.encode(imgData);
            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imgParam;

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = AuthService.getAuth();

            String result = HttpUtil.post(url, accessToken, param);
            Object object = JSON.parse(result);
            jsonResult = new JsonResult(Constants.STATUS_SUCCESS,"success", object);
        } catch (Exception e) {
            logger.error("error: ",e);
            jsonResult = new JsonResult(Constants.STATUS_ERROR,"error");
        }
        return jsonResult;
    }

    @RequestMapping("/asr")
    public JsonResult asrAdvancedGeneral(@RequestParam("file") MultipartFile file) {
        JsonResult jsonResult;
        try {
            TokenHolder holder = new TokenHolder(APP_KEY, SECRET_KEY, SCOPE);
            holder.resfresh();
            String token = holder.getToken();
            String result = null;
            String fileName = file.getOriginalFilename();
            String format = fileName.substring(fileName.length() - 3);
            if (METHOD_RAW) {
                result = runRawPostMethod(token, file.getBytes(), format);
            } else {
                result = runJsonPostMethod(token, file.getBytes(), format);
            }
            JSONObject jsonObject = JSON.parseObject(result);

            if ("0".equals(String.valueOf(jsonObject.get("err_no")))) {
                JSONArray jsonArray = JSONArray.parseObject(String.valueOf(jsonObject.get("result")), JSONArray.class);
                String res = jsonArray.getString(0).replaceAll("。", "");
                /*List<Word> words = WordSegmenter.seg(res);*/
                jsonResult = new JsonResult(Constants.STATUS_SUCCESS, "success", res);
            }else {
                jsonResult = new JsonResult(Constants.STATUS_FAIL, "语音识别失败，请稍后重试");
            }
        }catch (DemoException e) {
            jsonResult = new JsonResult(Constants.STATUS_FAIL, "语音识别失败，请稍后重试");
        } catch (IOException e) {
            jsonResult = new JsonResult(Constants.STATUS_FAIL, "语音识别失败，请稍后重试");
        }
        return jsonResult;
    }

    /**
     * 关键词查询垃圾分类
     */
    @RequestMapping("/lajifenlei")
    public JsonResult lajifenlei(HttpServletRequest request, RubbishWithSort record1, SearchRecord record2){
        JsonResult jsonResult;
        String name = record1.getName();
        try{
//            Map map = (Map) JSON.parse(HttpRequest.sendPost(url, params));
            List<RubbishWithSort> list = rubbishService.selectByName(record1);
            jsonResult = new JsonResult(Constants.STATUS_SUCCESS, "success", list);
            record2.setSearchName(name);
            searchRecordService.insertSelective(request, record2);
        }catch (Exception e){
            logger.error("error: ",e);
            jsonResult = new JsonResult(Constants.STATUS_ERROR, "error");
        }
        return jsonResult;
    }

    private String runRawPostMethod(String token, byte[] content, String format) throws IOException, DemoException {
        String url2 = URL + "?cuid=" + ConnUtil.urlEncode(CUID) + "&dev_pid=" + DEV_PID + "&token=" + token;
        //测试自训练平台需要打开以下信息
        //String url2 = URL + "?cuid=" + ConnUtil.urlEncode(CUID) + "&dev_pid=" + DEV_PID + "&lm_id="+ LM_ID + "&token=" + token;
        String contentTypeStr = "audio/" + format + "; rate=" + RATE;
        //System.out.println(url2);
        HttpURLConnection conn = (HttpURLConnection) new URL(url2).openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestProperty("Content-Type", contentTypeStr);
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.getOutputStream().write(content);
        conn.getOutputStream().close();
        System.out.println("url is " + url2);
        System.out.println("header is  " + "Content-Type :" + contentTypeStr);
        return ConnUtil.getResponseString(conn);
    }

    public String runJsonPostMethod(String token, byte[] content, String format) throws DemoException, IOException {
        String speech = base64Encode(content);

        JSONObject params = new JSONObject();
        params.put("dev_pid", DEV_PID);
        //params.put("lm_id",LM_ID);//测试自训练平台需要打开注释
        params.put("format", format);
        params.put("rate", RATE);
        params.put("token", token);
        params.put("cuid", CUID);
        params.put("channel", "1");
        params.put("len", content.length);
        params.put("speech", speech);

        // System.out.println(params.toString());
        HttpURLConnection conn = (HttpURLConnection) new URL(URL).openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        conn.setDoOutput(true);
        conn.getOutputStream().write(params.toString().getBytes());
        conn.getOutputStream().close();
        String result = ConnUtil.getResponseString(conn);


        params.put("speech", "base64Encode(getFileContent(FILENAME))");
        System.out.println("url is : " + URL);
        System.out.println("params is :" + params.toString());


        return result;
    }

    private String base64Encode(byte[] content) {
         Base64.Encoder encoder = Base64.getEncoder(); // JDK 1.8  推荐方法
         String str = encoder.encodeToString(content);

        /*char[] chars = Base64Util.encode(content); // 1.7 及以下，不推荐，请自行跟换相关库
        String str = new String(chars);*/

        return str;
    }

}
